/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium.kernel;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Properties;

/**
 * This class implements a mere data structure retaining all configuration
 * elements (parameters) that control the execution of an native runner. <br/>
 * Instances of this class are not mutable (but its streams are, of course,
 * modifiable).
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.1
 * @since 1.0
 */
public final class NativeParameters extends AbstractParameters {

    /** Whether backtrace should be simplified (Java elements are stripped). */
    private final boolean simplifiedBacktrace;

    /**
     * Constructs parameters from explicit values.
     * @param arguments arguments to program
     *                  - should not be <tt>null</tt>
     * @param backtrace whether backtrace is requested
     * @param exitStoppingJVM whether <i>exit</i> primitive should stop JVM
     * @param in standard input of program
     *           - should not be <tt>null</tt>
     * @param out standard output of program
     *            - should not be <tt>null</tt>
     * @param err standard error of program
     *            - should not be <tt>null</tt>
     * @param awt whether <i>Graphics</i> frame should be AWT
     * @param bareCanvas whether <i>Graphics</i> component should be a bare
     *                   canvas (no frame)
     * @param javaxSound whether <tt>javax.sound</tt> should be used for
     *                   <i>Graphics</i> beeps
     * @param jdbm whether <i>JDBM</i> should be used as the <i>Dbm</i> implementation
     * @param os underlying OS identifier - should not be <tt>null</tt>
     * @param unixEmulation whether unix primitives should be emulated
     * @param file file to be executed
     * @param embedded whether embedded mode is activated
     * @param embeddedBase base class for embedded mode
     * @param simplifiedBacktrace whether backtrace should be simplified
     */
    public NativeParameters(final String[] arguments,
                            final boolean backtrace,
                            final boolean exitStoppingJVM,
                            final InputStream in,
                            final PrintStream out,
                            final PrintStream err,
                            final boolean awt,
                            final boolean bareCanvas,
                            final boolean javaxSound,
                            final boolean jdbm,
                            final String os,
                            final boolean unixEmulation,
                            final String file,
                            final boolean embedded,
                            final String embeddedBase,
                            final boolean simplifiedBacktrace) {
        super(arguments, backtrace, exitStoppingJVM, in, out, err, awt,
              bareCanvas, javaxSound, jdbm, os, unixEmulation, file,
              embedded, embeddedBase);
        this.simplifiedBacktrace = simplifiedBacktrace;
    } // end constructor(String[], boolean, boolean, InputStream, ...)

    /**
     * Tests whether backtrace should be printed in simplified form
     * (Java elements are stripped).
     * @return <tt>true</tt> if backtrace should be simplified,
     *         <tt>false</tt> otherwise
     */
    public boolean isSimplifiedBacktrace() {
        return this.simplifiedBacktrace;
    } // end method 'isSimplifiedBacktrace()'

    /**
     * Constructs parameters from properties and additional elements. <br/>
     * The following properties and associated values are:
     * <ul>
     *   <li><tt>backtrace</tt>: <tt>on</tt> or <tt>off</tt>;</li>
     *   <li><tt>exitStoppingJVM</tt>: <tt>on</tt> or <tt>off</tt>;</li>
     *   <li><tt>awt</tt>: <tt>on</tt> or <tt>off</tt>;</li>
     *   <li><tt>javaxSound</tt>: <tt>on</tt> or <tt>off</tt>;</li>
     *   <li><tt>jdbm</tt>: <tt>on</tt> or <tt>off</tt>;</li>
     *   <li><tt>os</tt>: any of <tt>Unix</tt>, <tt>Cygwin</tt>,
     *       <tt>Win32</tt>, <tt>MacOS</tt>, or <tt>Cadmium</tt>;</li>
     *   <li><tt>unixEmulation</tt>: <tt>on</tt> or <tt>off</tt>.</li>
     * </ul>
     * @param is stream to load properties from - should not be <tt>null</tt>
     * @param args application arguments - should not be <tt>null</tt>
     * @param in standard input - should not be <tt>null</tt>
     * @param out standard output - should not be <tt>null</tt>
     * @param err standard error - should not be <tt>null</tt>
     * @param bareCanvas whether to display <i>Graphics</i> frame
     * @param file name of file to execute - should not be <tt>null</tt>
     * @return corresponding parameters
     * @throws CadmiumException if an error occurs when converting a parameter
     *                          value
     */
    public static NativeParameters fromStream(final InputStream is,
                                              final String[] args,
                                              final InputStream in,
                                              final PrintStream out,
                                              final PrintStream err,
                                              final boolean bareCanvas,
                                              final String file)
        throws CadmiumException {
        assert is != null : "null is";
        assert args != null : "null args";
        assert in != null : "null in";
        assert out != null : "null out";
        assert err != null : "null err";
        assert file != null : "null file";
        final int len = args.length;
        final String[] argsWithFile = new String[len + 1];
        System.arraycopy(args, 0, argsWithFile, 1, len);
        argsWithFile[0] = file;
        try {
            final Properties p = new Properties();
            p.load(is);
            return new NativeParameters(argsWithFile,
                                        valueOfBoolean(p.getProperty("backtrace", "off")),
                                        valueOfBoolean(p.getProperty("exitStoppingJVM", "on")),
                                        in,
                                        out,
                                        err,
                                        valueOfBoolean(p.getProperty("awt", "off")),
                                        bareCanvas,
                                        valueOfBoolean(p.getProperty("javaxSound", "off")),
                                        valueOfBoolean(p.getProperty("jdbm", "off")),
                                        valueOfOS(p.getProperty("os", "Unix")),
                                        valueOfBoolean(p.getProperty("unixEmulation", "off")),
                                        file,
                                        valueOfBoolean(p.getProperty("embedded", "off")),
                                        p.getProperty("embeddedBase", ""),
                                        valueOfBoolean(p.getProperty("simplifiedBacktrace", "on")));
        } catch (final IOException ioe) {
            throw new CadmiumException("unable to load parameters", ioe);
        } // end try/catch
    } // end method 'fromStream(InputStream, String[], InputStream, ...)'

} // end class 'NativeParameters'
